#-*- coding: utf-8 -*-

'''
autor1: João Reis, Nº5236
autor2: Miguel Romão, Nº5513
data: 21 de Outubro 2013
obs: Criação da Base de Dados
'''

import os
from ler_dados_xls import *
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()

class Tabela_Dados(Base):
	'''
		Esta classe serve como objecto para	fazer o preenchimento 
		da Tabela 'concurso_nacional_2013' na Base de Dados.
	'''
	__tablename__ = 'concurso_nacional_2013'

	#estrutura da tabela concurso_nacional_2013
	id = Column(Integer, primary_key = True)
	Codigo_da_Instituicao = Column(Integer)
	Codigo_do_Curso = Column(String)
	Nome_da_Instituicao = Column(String)
	Nome_do_Curso = Column(String)
	Grau = Column(String)
	Vagas_Iniciais = Column(Integer)
	Colocados = Column(Integer)
	Nota_Candidatura = Column(Float)
	Vagas_Sobrantes = Column(Integer)

	def __init__(self, Codigo_da_Instituicao, Codigo_do_Curso, Nome_da_Instituicao, 
		Nome_do_Curso, Grau, Vagas_Iniciais, Colocados, Nota_Candidatura, 
		Vagas_Sobrantes):
	    self.Codigo_da_Instituicao = Codigo_da_Instituicao
	    self.Codigo_do_Curso = Codigo_do_Curso
	    self.Nome_da_Instituicao = Nome_da_Instituicao
	    self.Nome_do_Curso = Nome_do_Curso
	    self.Grau = Grau
	    self.Vagas_Iniciais = Vagas_Iniciais
	    self.Colocados = Colocados
	    self.Nota_Candidatura = Nota_Candidatura
	    self.Vagas_Sobrantes = Vagas_Sobrantes

class Tabela_Distritos(Base):
	'''
		Esta classe serve como objecto para fazer o preenchimento 
		da Tabela 'distritos' na Base de Dados.
	'''
	__tablename__ = 'distritos'

	#estrutura da tabela distritos
	id = Column(Integer, primary_key = True)
	nome_do_distrito = Column(String)

	def __init__(self, nome_do_distrito):
	    self.nome_do_distrito = nome_do_distrito

class Tabela_Institutos(Base):
	'''
		Esta classe serve como objecto para	fazer o preenchimento 
		da Tabela 'institutos' na Base de Dados.
	'''
	__tablename__ = 'institutos'

	#estrutura da tabela institutos
	id = Column(Integer, primary_key = True)
	nome_do_instituto = Column(String)
	nome_do_distrito = Column(Integer, ForeignKey('distritos.nome_do_distrito'))

	def __init__(self, nome_do_instituto, nome_do_distrito):
	    self.nome_do_instituto = nome_do_instituto
	    self.nome_do_distrito = nome_do_distrito

class BaseDados:
	'''
		Esta classe contém as funções para criar e preencher a Base de Dados.
	'''
	
	def criar_bd(self, nome_base_dados):
		'''
			Função que cria a base de dados.

			Args:
					nome_base_dados: o nome do ficheiro da base de dados.
			
			Returns:
					o 'engine' que conecta à base de dados.
		'''

		# cria uma pasta para guardar a base de dados se esta não existir
		if not os.path.exists('base_dados'):
			os.makedirs('base_dados')

		base_dados = create_engine('sqlite:///base_dados/' + nome_base_dados, 
			echo=False)
		# apaga todas as tabelas presentes na base de dados
		Base.metadata.drop_all(base_dados)
		# cria novas tabelas na base de dados
		Base.metadata.create_all(base_dados)
		
		return base_dados

	def preencher_tabela_dados(self, ficheiro_xls, base_dados):
		'''
			Função que preenche a tabela 'concurso_nacional_2013' na base de dados.

			Args:
					ficheiro_xls: nome do ficheiro '.xls'.
					base_dados: conector da base de dados.
		'''
		Session = sessionmaker(bind = base_dados)
		sessao = Session()
		
		leitor = LeituraDados(ficheiro_xls)

		# ciclo que lê linha a linha o documento '.xls' e enviar os dados lidos
		# para a tabela concurso_nacional_2013 da base de dados
		for x in range(3, leitor.folha.nrows - 2):
			lista = leitor.ler_dados(x)

			objeto = Tabela_Dados(lista[0], lista[1], lista[2].decode('utf-8'),
				lista[3].decode('utf-8'), lista[4], lista[5], lista[6],
				lista[7], lista[8])

			sessao.add(objeto)
			del objeto, lista
		
		sessao.commit()

	def preencher_tabela_distritos(self, base_dados):
		'''
			Função que preenche a tabela 'distritos' na base de dados.

			Args:
					base_dados: conector da base de dados.
		'''
		Session = sessionmaker(bind = base_dados)
		sessao = Session()

		# lista dos distritos retirada do link do trabalho
		distritos = ['Distrito de Lisboa', 'Distrito do Porto', 'Distrito de Setúbal',
			'Distrito de Braga', 'Distrito de Aveiro', 'Distrito de Leiria',
			'Distrito de Santarém', 'Distrito de Faro', 'Distrito de Coimbra', 
			'Distrito de Viseu', 'R. A. Madeira', 'R. A. Açores', 
			'Distrito de Viana do Castelo', 'Distrito de Vila Real', 
			'Distrito de Castelo Branco', 'Distrito de Évora', 'Distrito da Guarda', 
			'Distrito de Beja', 'Distrito de Bragança', 'Distrito de Portalegre']

		for nome in distritos:
			objecto = Tabela_Distritos(nome.decode('utf-8'))
			sessao.add(objecto)
		
		sessao.commit()

	def atribuir_distritos(self, lista_institutos):
		'''
			Função que atribui a cada instituto o distrito a que pertence.

			Args:
					lista_institutos: a lista com todas as instituições.
			
			Returns:
					uma lista de pares compostos por nome da instituição e 
					nome do distrito a que pertence.
		'''
		lista_institutos_distritos = []

		# ciclo para atribuir a cada instituição o distrito a que pertence
		for x in xrange(len(lista_institutos)):
			lista_temp = []
			if x == 0 or x == 2 or x == 4 or x == 5 or x == 12 or x == 21 \
				or x == 22 or x == 27:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Lisboa'])
			elif x == 3 or x == 20 or x == 32:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito do Porto'])
			elif x == 15:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Setúbal'.decode('utf-8')])
			elif x == 31:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Braga'])
			elif x == 25:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Aveiro'])
			elif x == 11:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Leiria'])
			elif x == 14 or x == 16:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Santarém'.decode('utf-8')])
			elif x == 30:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Faro'])
			elif x == 1 or x == 10 or x == 26:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Coimbra'])
			elif x == 18:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Viseu'])
			elif x == 24:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'R. A. Madeira'])
			elif x == 33:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'R. A. Açores'.decode('utf-8')])
			elif x == 17 or x == 19:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Viana do Castelo'])
			elif x == 28:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Vila Real'])
			elif x == 9:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Castelo Branco'])
			elif x == 29:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Évora'.decode('utf-8')])
			elif x == 6 or x == 23:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito da Guarda'])
			elif x == 7:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Beja'])
			elif x == 8:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Bragança'.decode('utf-8')])
			elif x == 13:
				lista_temp.extend([lista_institutos[x].decode('utf-8'), 
					'Distrito de Portalegre'])
			lista_institutos_distritos.append(lista_temp)
			del lista_temp

		return lista_institutos_distritos

	def preencher_tabela_instituicao(self, ficheiro_xls, base_dados):
		'''
			Função que preenche a tabela 'institutos' na base de dados.

			Args:
					ficheiro_xls: nome do ficheiro '.xls'.
					base_dados: conector da base de dados.
		'''
		Session = sessionmaker(bind = base_dados)
		sessao = Session()

		leitor = LeituraDados(ficheiro_xls)
		lista_institutos = leitor.ler_institutos()
		lista_institutos_distritos = self.atribuir_distritos(lista_institutos)

		# ciclo que envia para a tabela institutos da base de dados, a lista de
		# instituições com os distritos a que pertencem
		for x in xrange(len(lista_institutos)):
			objecto = Tabela_Institutos(lista_institutos_distritos[x][0],
				lista_institutos_distritos[x][1])
			sessao.add(objecto)
		
		sessao.commit()